Authentication Security & Vulnerabilities
Authentication Basics
-
Authentication = verifying user identity
- Maps request → specific user row in database
-
Core question:
- “Who is this user?”
Why Authentication Matters
-
If broken:
- Attackers can impersonate users
- Access private data
- Perform actions on behalf of users
- Steal money (critical in payment systems)
Real-World Risk
-
Account takeover vulnerabilities are:
- Common
- High-impact
-
Seen frequently in production systems
Recommendation: Use Auth Providers
Advice
- Avoid building authentication from scratch (especially in production)
Why Use Auth Providers
-
Saves:
- Development time
- Engineering effort
-
Handles:
- Security edge cases
- Scaling complexity
-
Provides:
- Better UX
- Battle-tested security
Features They Handle
- Stateful session management
- Multi-device login tracking
- Session revocation
- OAuth (Google, GitHub, etc.)
- Role-Based Access Control (RBAC)
Complexity of DIY Auth
Stateful Authentication Challenges
-
Requires:
- Databases
- Caching (e.g., Redis)
-
Needs:
- Session tracking
- Revocation mechanisms
- Expiry handling
OAuth Integration Challenges
-
Implement:
- Redirect flows
- Token exchange
-
Handle:
- Linking accounts (email vs Google login)
Example Problem
-
Same user:
- Logs in via email/password
- Then logs in via Google
-
System must:
- Recognize them as same user
Conclusion
-
Auth providers:
- Solve edge cases
- Handle security continuously
-
Recommended:
- Use provider initially
- Build custom solution later (if scale demands)
Password Storage
Wrong Approach: Plain Text Storage
-
Store password directly in DB:
password = "12345"
Problems
1. Database Breaches
-
Passwords exposed instantly
-
Common scenario:
- Third-party breach
- Insider threat
2. Password Reuse
- ~70% users reuse passwords
- One breach → compromises multiple platforms
3. Internal Risk
-
Developers/DB admins can:
- See all user passwords
Conclusion
- ❌ Never store passwords in plain text
Hashing
Definition
-
Hash function:
- Takes input → returns fixed-length output
Properties
-
Deterministic:
- Same input → same output
-
Fixed length:
- Output size constant
-
One-way:
- Cannot reverse hash → original input
Usage
-
Store:
hash(password) -
During login:
- Hash input password
- Compare with stored hash
Benefit
-
Even if DB leaks:
- Passwords are not directly exposed
Problem: Rainbow Table Attacks
What is Rainbow Table
-
Precomputed mapping:
- Password → Hash
Attack Method
- Match leaked hashes with known hashes
- Recover common passwords
Vulnerability
- Same password → same hash
- Enables reverse lookup
Solution: Salting
Definition
- Add random value (salt) to password before hashing
Process
-
Generate random salt per user
-
Store:
- Salt
- Hash(password + salt)
Effect
-
Same password:
- Produces different hashes
-
Rainbow tables become useless
Key Requirement
-
Salt must be:
- Random
- Unique per user
- Cryptographically secure
Problem: Brute Force Attacks
Modern Threat
-
GPUs can compute:
- Billions of hashes per second
Attack
-
Try:
- Password + salt combinations
-
Match with stored hash
Solution: Slow Hashing
Why Not SHA-256 / MD5
- Too fast → easy brute force
Use Slow Hash Functions
-
Examples:
- bcrypt
- scrypt
- Argon2id (modern standard)
- Lucia (Should Read it)
Key Feature: Cost Factor
-
Controls:
- Computation time per hash
Tradeoff
-
For users:
- Slight delay (~100–500 ms)
-
For attackers:
- Massive slowdown
Result
-
Brute force becomes:
- Impractical (years/decades)
Sessions (Stateful Authentication)
Purpose
- Avoid asking password on every request
Flow
Step 1: Generate Session ID
- Random string (128–256 bits)
Step 2: Store in Backend
-
DB or cache (e.g., Redis)
-
Store metadata:
- User ID
- Expiry
- IP
- User agent
Step 3: Send to Client
- Stored in cookie
Request Flow
-
Client sends session ID
-
Server:
- Looks up session
- Identifies user
Security Requirement
-
Session ID must be:
- Unguessable
- Cryptographically random
Cookie Security
HTTPOnly
-
Prevents JavaScript access
-
Protects against:
- XSS stealing cookies
Secure Flag
-
Cookie sent only over HTTPS
-
Prevents:
- Network interception
SameSite
Strict
- Only same-origin requests
Lax
- Allows top-level navigation
- Blocks iframe/image-based attacks
Why iframe/images blocked? CSRF (Cross Site Request Forgery) -> Making use of Images/ Iframes to trick our server into believing that the request is a genuine request originating from our platform or our site or our frontend.
None
- Sent everywhere (least secure)
Recommendation
-
Use:
HTTPOnly = trueSecure = trueSameSite = Strict/Lax
JWT (Stateless Authentication)
Difference from Sessions
-
No server storage
-
Token contains:
- All session data
Structure
- Header → algorithm info
- Payload → user data (claims)
- Signature → verification
Flow
-
Server:
- Creates token
- Signs with secret
-
Client:
- Stores token
- Sends with each request
-
Server:
- Verifies signature
- Trusts payload
Key Property
- Tampering invalidates signature
JWT Vulnerabilities
1. Revocation Problem
-
Cannot easily:
- Log out users globally
-
Token remains valid until expiry
Workarounds
Blacklisting
- Store invalid tokens
Short Expiry + Refresh Tokens
-
Access token:
- Short-lived (5–10 min)
-
Refresh token:
- Long-lived (1–7 days)
2. Payload Visibility
- JWT payload = Base64 encoded (not encrypted)
- Anyone can read it
Rule
- ❌ Do NOT store sensitive data in JWT
3. Storage Issue
Local Storage
- Vulnerable to XSS
Cookies
-
Safer if:
- HTTPOnly enabled
Recommendation: Sessions vs JWT
Prefer Stateful Sessions
-
Easier:
- Revocation
- Control
-
Simpler architecture
-
In case of scaling also, make use of distributed key value pair based databases like Redis to store the user sessions.
-
Even the revocations strategies are simple.
Use JWT Only If
-
You need:
- Horizontal scaling
- Distributed systems
Best Practices for JWT
- Short expiry
- Use refresh tokens
- Store in HTTPOnly cookies
Rate Limiting (Critical Security Layer)
Problem Without Rate Limiting
-
Attackers can:
- Try millions of passwords
- Crash server (DoS)
Solution
-
Limit:
- Requests per time window
Strategies
1. Per-IP Rate Limiting
-
Example:
- 10 attempts/minute
Limitation
-
Shared IPs (colleges, offices)
-
Attackers use:
- VPNs
- Botnets
- Rotating IPs
Recommendation
-
Use:
- Multi-layer rate limiting
-
Be stricter on:
- Authentication endpoints
-
Be relaxed on:
- General APIs
Final Security Takeaways
Core Principles
- Never trust user input
- Avoid assumptions
- Use proven libraries
Authentication Checklist
- Use auth providers (if possible)
- Hash + salt passwords
- Use slow hashing (Argon2/bcrypt)
- Use secure cookies
- Prefer sessions over JWT
- Implement rate limiting
Mental Model
-
Always ask:
- “How can this be abused?”